// main.rs

use std::fs;
use std::path::Path;
// 从我们自己的库 (crate) 中引入 Memory 结构体
use riscv_sim::mem::Memory; 
use riscv_sim::mem::DumpOptions;
use riscv_sim::common::print_hello_form_common_module;
use riscv_sim::periph::print_hello_form_peripheral_module_uart;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // --- 日志初始化 (推荐) ---
    // 这是一个好习惯，让你能看到 load_image 等函数中的 log::info! 输出
    env_logger::init();

    print_hello_form_common_module();
    print_hello_form_peripheral_module_uart();

    let bin_path_str: &'static str = "D:\\Users\\92439\\Documents\\00_ThinkB16P\\04_RiscV\\update-x-bin";
    let bin_path: &Path = Path::new(bin_path_str);

    // 检查文件是否存在
    if !bin_path.exists() {
        // 使用 log::error! 或 eprintln! 打印错误，这比直接 panic 更优雅
        log::error!("错误：二进制文件 '{}' 不存在。", bin_path_str);
        // 返回一个标准的错误，而不是直接 panic
        // 这里我们创建一个简单的字符串错误并将其转换为 Box<dyn Error>
        return Err(format!("文件未找到: {}", bin_path_str).into());
    }

    // 1. 创建内存实例
    let mut memory = Memory::new(0x8000_0000, 2 * 1024 * 1024);
    
    // 2. 读取并加载BIN文件
    let metadata = fs::metadata(bin_path)?;
    let metadata_len = metadata.len();
    log::info!("文件大小: {} 字节", metadata_len);
    println!("文件大小: {} 字节", metadata_len);
    
    if metadata_len == 0 {
        return Err("二进制文件为空".into());
    }
    // 使用 ? 操作符来优雅地处理 fs::read 和 load_image 可能返回的错误
    let bin_data = fs::read(bin_path)?;
    memory.load_image(0x8000_0000, &bin_data)?;

    // 3. 验证内存中的关键指令
    log::info!("--- 开始验证内存内容 ---");
    
    let first_instruction = memory.read_u32(0x8000_0000)?;
    let expected_first = 0x02A00513;
    if first_instruction != expected_first {
        return Err(format!(
            "地址 0x80000000 处的指令不匹配！期望: 0x{:08X}, 实际: 0x{:08X}",
            expected_first, first_instruction
        ).into());
    }
    log::info!("第一条指令验证成功: 0x{:08X}", first_instruction);

    let second_instruction = memory.read_u32(0x8000_0004)?;
    let expected_second = 0x018000EF;
    if second_instruction != expected_second {
        return Err(format!(
            "地址 0x80000004 处的指令不匹配！期望: 0x{:08X}, 实际: 0x{:08X}",
            expected_second, second_instruction
        ).into());
    }
    log::info!("第二条指令验证成功: 0x{:08X}", second_instruction);

    // 打印内存快照以供人工核对
    println!("\n--- 加载 BIN 文件后的内存快照 ---");
    println!("{:#?}", memory);
    
    // 创建类似于图片中的转储配置
    let options = DumpOptions {
        bytes_per_line: 16,
        max_lines: 70,          // 图片显示68行
        show_ascii: false,      // 图片中没有ASCII列
        compress_empty_lines: true,    // 图片中显示所有行
        show_line_numbers: true,        // 图片中显示行号
    };
    
    memory.dump_to_file("memory_dump.txt", &options)?;

    // main 函数成功结束
    Ok(())
}
